// resolve 和 reject 最终都会调用该函数
var final = function (status, value) {
    let p = this, fn;

    if (p.status !== 'PENDING') return;

    setTimeout(function () {
       p.status = status;

       let quene = status === 'FULFILLED' ? p['_resolves'] : p['_rejects'];

       while (fn = quene.shift()) {
           value = fn.call(p, value) || value;
       }

        p.value = value;
        p['_resolves'] = p['_rejects'] = undefined;
    });
}


//参数是一个函数，内部提供两个函数作为该函数的参数,分别是resolve 和 reject
var Promise = function (resolver) {

    if (!(typeof resolver === 'function'))
        throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');


    var p = this;
    p.value;
    p.status = 'PENDING';
    //存储状态
    p._resolves = [];
    p._rejects = [];

    var resolve = function (v) {
        final.apply(p, ['FULFILLED', v]);
    }

    var reject = function (v) {
        final.apply(p, ['REJECTED', v]);
    }

    resolver(resolve, reject);
}

Promise.prototype.then = function (onFulfilled, onRejected) {
    var p = this;
    // 每次返回一个promise，保证是可thenable的
    return new Promise(function (resolve, reject) {

        function handle(value) {
            // 這一步很關鍵，只有這樣才可以將值傳遞給下一個resolve
            var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value;

            //判断是不是promise 对象
            if (ret && typeof ret ['then'] == 'function') {
                ret.then(function (value) {
                    resolve(value);
                }, function (reason) {
                    reject(reason);
                });
            } else {
            }
        }

        function errback(reason) {
            reason = typeof onRejected === 'function' && onRejected(reason) || reason;
            reject(reason);
        }

        if (p.status === 'PENDING') {

            p._resolves.push(handle);
            p._rejects.push(errback);
        } else if (p.status === 'FULFILLED') { // 状态改变后的then操作，立刻执行
            callback(p.value);
        } else if (p.status === 'REJECTED') {
            errback(p.value);
        }
    });
}

Promise.prototype.resolves = function (arg) {
    return new Promise((resolve, reject) => {
        resolve(arg)
    })
}

Promise.prototype.reject = function (arg) {
    return new Promise((resolve, reject) => {
        reject(arg)
    })
}

let promise = new Promise((resolve, reject) => {
    console.log('Promise');
    reject();
});

promise.then(function () {
    console.log('Resolved.');
}).then(e => console.log('finally'));

console.log('Hi!');